namespace Profit
{
    using System;
    using System.Threading;
    using System.Windows;
    using System.Windows.Threading;
    using Core.Contracts.Interfaces;
    using System.Diagnostics;

    public sealed class ClipboardExplorer
    {
        private Timer _timer;
        private readonly TimeSpan _delay = TimeSpan.FromSeconds(5);
        private readonly Dispatcher _dispatcher;
        private string _ignore;
        /// <summary>
        /// Occurs when a fitting is stored in the clipboard
        /// </summary>
        public event EventHandler<FittingStoredEventArgs> FittingStored;

        /// <summary>
        /// Creates a new instance
        /// </summary>
        public ClipboardExplorer(Dispatcher dispatcher)
            : this(dispatcher, TimeSpan.FromSeconds(5))
        {
        }

        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="dispatcher"></param>
        /// <param name="delay">The polling timer delay</param>
        public ClipboardExplorer(Dispatcher dispatcher, TimeSpan delay)
        {
            _dispatcher = dispatcher;
            _delay = delay;
        }

        public void IgnoreFitting(string name)
        {
            _ignore = name;
        }

        public void Stop()
        {
            _timer.Dispose();
            _timer = null;
        }

        public void Start()
        {
            if(_timer!=null)
                Stop();

            _timer = new Timer(OnTimeElapsed, null, _delay, _delay);
        }

        /// <summary>
        /// Checks the clipboard text content for a fitting.
        /// If a fitting is present, clears the clipboard and raises the FittingStored event.
        /// </summary>
        public void CheckForStoredFitting()
        {
            if (!HasFittingStored()) return;

            var content = Clipboard.GetText(TextDataFormat.Text);
            Clipboard.Clear();
            _ignore = null;

            Trace.TraceInformation("Fitting \"{0}\" found in clipboard",content.GetFittingName());
            InvokeFittingStored(new FittingStoredEventArgs(content));
        }
        /// <summary>
        /// Determines if the clipboard contains a not ignored fitting.
        /// </summary>
        /// <returns></returns>
        public bool HasFittingStored()
        {
            if (!Clipboard.ContainsText(TextDataFormat.Text) ||
                !Clipboard.GetText(TextDataFormat.Text).IsFittingTextFormat()) return false;

            var content = Clipboard.GetText(TextDataFormat.Text);
            return !string.Equals(_ignore, content.GetFittingName());
        }
        /// <summary>
        /// Obtains the fitting stored in the clipboard and clear the clipboard
        /// </summary>
        /// <returns>An IFitting instance or null</returns>
        public IFitting GetFitting()
        {
            var content = Clipboard.GetText(TextDataFormat.Text);
            Clipboard.Clear();
            _ignore = null;
            return content.ToFitting();
        }
        /// <summary>
        /// Raises the FittingStored event
        /// </summary>
        /// <param name="e"></param>
        private void InvokeFittingStored(FittingStoredEventArgs e)
        {
            var handler = FittingStored;
            if (handler != null) handler(this, e);
        }

        private void OnTimeElapsed(object state)
        {
            _dispatcher.Invoke(new ActionDelegate(CheckForStoredFitting));
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public sealed class FittingStoredEventArgs : EventArgs
    {
        private readonly string _content;
        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="content">The fitting text</param>
        public FittingStoredEventArgs(string content)
        {
            _content = content;
        }
        /// <summary>
        /// Otains the name of the fitting
        /// </summary>
        public string Name
        {
            get { return _content.GetFittingName(); }
        }
        /// <summary>
        /// Obtains the name of the robot
        /// </summary>
        public string RobotName
        {
            get { return _content.GetFittingRobotName(); }
        }

        /// <summary>
        /// Obtains the Fitting instance from the content
        /// </summary>
        public IFitting Fitting
        {
            get { return string.IsNullOrEmpty(_content) ? null : _content.ToFitting(); }
        }
    }
}